package yxy.game.pm2.module.stairway;

import java.util.*;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import org.joda.time.DateTime;

import org.redisson.api.RMap;
import yxy.apple.util.RandomUtility;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.sportsdate;
import yxy.cherry.data.bean.sportsrankreward;
import yxy.cherry.data.bean.sportsrobot;
import yxy.cherry.data.script.fomula;
import yxy.cherry.data.string.GameString;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format.FormatType;
import yxy.game.pm2.bean.PlayerBean;
import yxy.game.pm2.bean.ServerBean;
import yxy.game.pm2.bean.area.AreaBean;
import yxy.game.pm2.bean.area.AreaGroupBean;
import yxy.game.pm2.bean.currency.Currencies;
import yxy.game.pm2.bean.currency.CurrencyNotEnoughException;
import yxy.game.pm2.bean.currency.CurrencyType;
import yxy.game.pm2.bean.module.rank.RankEntry;
import yxy.game.pm2.bean.mq.CCReason;
import yxy.game.pm2.message.BattleMessage;
import yxy.game.pm2.message.HeroMessage;
import yxy.game.pm2.message.PlayerMessage;
import yxy.game.pm2.message.StairwayMessage;
import yxy.game.pm2.message.StairwayMessage.StairwayChanllengeResponse.Builder;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.arena.RankArena;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.mail.MailHandle;
import yxy.game.pm2.module.mail.MailTypeEnum;
import yxy.game.pm2.module.stat.StatHandle;

public class StairwayHandle {

	public Result stairway(int areaGroupId, String playerCode, StairwayMessage.StairwayUIResponse.Builder response) {
		DateTime now = DateTime.now();
		boolean isOpen = StairwayHandle.isOpen(areaGroupId);
		DateTime updateTime = StairwayHandle.updateTime(now);

		StairwayPlayerModule stairwayPlayerModule = StairwayPlayerModule.get(playerCode);
		if (stairwayPlayerModule == null) {
			response.setOpen(false);
			return Result.ModuleNotOpen;
		}

		if (isOpen) {
			RankStairway rankStairway = new RankStairway(areaGroupId);
			Map<String, sportsrobot> all = DataCenter.getAllData(sportsrobot.class);
			int rank = 0;
			RankEntry rankEntry = rankStairway.get(stairwayPlayerModule.getPlayerCode());
			if (rankEntry != null) {
				rank = rankEntry.getValue().intValue();
			}
			LinkedList<Integer> list = randomMatch(rankEntry == null ? all.size() + 1 : rank);
			stairwayPlayerModule.getOppos().clear();
			stairwayPlayerModule.getOppos().addAll(list);
			stairwayPlayerModule.set();

			Collection<RankEntry> entrys = rankStairway.range((long) list.getLast(), (long) list.getFirst());

			for (Integer r : list) {
				boolean isPlayer = false;
				for (RankEntry entry : entrys) {
					int rvalue = entry.getValue().intValue();
					if (rvalue == r) {
						StairwayMessage.StairwayRank info = info(r, entry);
						response.addShow(info);
						isPlayer = true;
						break;
					}
				}
				if (isPlayer) {
					continue;
				}
				sportsrobot robot = all.get(String.valueOf(r));
				StairwayMessage.StairwayRank info = info(r, robot);
				response.addShow(info);
			}

			response.setRank(rank);
		}

		response.setOpen(isOpen);
		response.setUpdateTime(updateTime.getMillis());
		response.setTimes(stairwayPlayerModule.remainTimes());
		response.setBuytimes(stairwayPlayerModule.remainBuyTimes());

		return Result.Success;
	}

	private StairwayMessage.StairwayRank info(int rank, RankEntry entry) {
		String playerCode = entry.getKey();
		int floor = entry.getValue().intValue();
		StairwayMessage.StairwayRank.Builder rankInfo = StairwayMessage.StairwayRank.newBuilder();
		PlayerBean player = PlayerBean.get(playerCode);

		PlayerMessage.PlayerSimpleInfo.Builder builder = PlayerMessage.PlayerSimpleInfo.newBuilder();
		builder.setNickname(player.getName());
		builder.setHead(player.getHead());
		builder.setAvatar(player.getAvatar());
		builder.setPower(player.getPower());

		rankInfo.setRank(rank);
		rankInfo.setFloor(floor);
		rankInfo.setPlayerInfo(builder);

		return rankInfo.build();
	}

	private StairwayMessage.StairwayRank info(int rank, sportsrobot robot) {
		StairwayMessage.StairwayRank.Builder rankInfo = StairwayMessage.StairwayRank.newBuilder();

		PlayerMessage.PlayerSimpleInfo.Builder builder = PlayerMessage.PlayerSimpleInfo.newBuilder();
		builder.setNickname(robot.getName());
		builder.setHead(robot.getHeadid());
		builder.setAvatar(robot.getAvatar());

		//战力根据实际计算从缓存获取
		ArrayList<FighterModule> fighterModuleList = getFighterModuleList(rank);
		long totalPower = 0;
		for (FighterModule fighterModule : fighterModuleList) {
			totalPower +=fighterModule.getTotalPower();
		}
		builder.setPower(totalPower);

		rankInfo.setRank(rank);
		rankInfo.setFloor(robot.getId());
		rankInfo.setPlayerInfo(builder);

		return rankInfo.build();
	}

	private LinkedList<Integer> randomMatch(int rank) {
		LinkedList<Integer> list = new LinkedList<>();
		if (rank <= 5) {
			for (int r = 5; r > 0; r--) {
				list.addFirst(r);
			}
			return list;
		}
		int min = rank / 100;
		int max = rank / 10;
		min = min < 1 ? 1 : min;
		max = max < 1 ? 1 : max;
		for (int i = 0; i < 5; i++) {
			int r = RandomUtility.nextInt(min, max + 1);
			rank -= r;
			list.addFirst(rank);
		}

		return list;
	}

	static public sportsdate data() {
		return DataCenter.getData(1, sportsdate.class);
	}

	// 战斗处理===========================================================================

	private String code() {
		return BattleType.STAIRWAY.name();
	}

	/** 检查竞技场排名 */
	public boolean checkArenaRank(String playerCode) {
		int rank = RankArena.getRank(playerCode).rank(playerCode);
		return rank > 0 && rank <= 100;
	}

	public Result battleResponseExecute(StairwayPlayerModule stairwayModuleA, int rank, Builder response) {
		String playerCode = stairwayModuleA.getPlayerCode();
		if (!checkArenaRank(playerCode)) {
			return Result.StairwayArenaRankNotFit;// 竞技场排名不够
		}
        PlayerBean playerBean = PlayerBean.get(playerCode);
        ServerBean serverBean = ServerBean.get(playerBean.getServerId());
        AreaBean areaBean = AreaBean.get(serverBean.getAreaId());

		DateTime now = DateTime.now();
		int playerRank = 0;
		RankStairway rankStairway = new RankStairway(areaBean.getGroupId());
		RankEntry entry = rankStairway.get(playerCode);
		if (entry != null) {
			playerRank = entry.getValue().intValue();
			if (rank >= playerRank) {
				// 排名比玩家低 或 同玩家排名一样（玩家本人）
				return Result.StairwayCantChanllenge;// 不能挑战这个位置的玩家
			}
		}
		Result result = costTimes(stairwayModuleA);
		if (!result.equals(Result.Success)) {
			return result;
		}

		PlayerBean playerBeanB = playerByRank(areaBean.getGroupId(), rank);

		BattleHandle battleHandle = new BattleHandle();

		BattleModule battleModule = BattleModule.create(playerCode);
		battleModule.setType(BattleType.STAIRWAY);
		battleModule.setCode(code());

		// 玩家的team
		TeamModule teamA = battleHandle.teamPlayer(playerCode, FormatType.普通);
		battleModule.setTeamA(teamA);

		// 对手的team
		TeamModule teamB = team(areaBean.getGroupId(), rank);
		if (teamB == null) {
			return Result.DataError;
		}
		battleModule.setTeamB(teamB);

		Team team_a = teamA.team(true);
		Team team_b = teamB.team(false);
		team_a.setTeam对手(team_b);
		team_b.setTeam对手(team_a);

		// 处理战斗
		battleHandle.battleExecute(battleModule, team_a, team_b, 20);

		boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

		sportsdate data = data();
		Currencies rewards = new Currencies();

		if (isWin) {
			// 交换排名
			rankStairway.put(playerCode, rank);
			if (stairwayModuleA.getBestRank() == 0 || stairwayModuleA.getBestRank() > rank) {
				stairwayModuleA.setBestRank(rank);
			}

			if (playerBeanB != null) {
				if (playerRank <= 0) {
					rankStairway.remove(playerBeanB.getCode());
				} else {
					rankStairway.put(playerBeanB.getCode(), playerRank);
				}
			}
			rewards.add(Currency.create(data.getWingettype(), data.getWingetid(), data.getWingetnum()));
		} else {
			rewards.add(Currency.create(data.getFailgettype(), data.getFailgetid(), data.getFailgetnum()));
		}
		// 处理奖励
		new CurrencyHandle().addCurrency(playerCode, CCReason.天梯争雄, rewards);

		// 处理录像
		BattleRecord battleRecord = battleModule.saveRecord(BattleRecord.randomCode(), 1);
		{
			// 进攻者记录
			StairwayRecord stairwayRecord = new StairwayRecord();
			stairwayRecord.setDate(now);
			stairwayRecord.setRecordCode(battleRecord.getCode());
			stairwayRecord.setAttacker(true);
			stairwayRecord.setBattleResult(battleModule.getBattleResult());
			stairwayRecord.setRank(isWin ? rank : playerRank);

			stairwayRecord.setName(teamB.getName());
			stairwayRecord.setHead(teamB.getHead());
			stairwayRecord.setPower(teamB.getPower());
			stairwayRecord.setLevel(teamB.getLevel());

			StairwayRecord.add(playerCode, stairwayRecord);
		}
		// 防守者记录
		if (playerBeanB != null) {
			StairwayRecord stairwayRecord = new StairwayRecord();
			stairwayRecord.setDate(now);
			stairwayRecord.setRecordCode(battleRecord.getCode());
			stairwayRecord.setAttacker(false);
			stairwayRecord.setBattleResult(battleModule.getBattleResult());
			stairwayRecord.setRank(isWin ? playerRank : rank);

			stairwayRecord.setName(teamA.getName());
			stairwayRecord.setHead(teamA.getHead());
			stairwayRecord.setPower(teamA.getPower());
			stairwayRecord.setLevel(teamA.getLevel());

			StairwayRecord.add(playerBeanB.getCode(), stairwayRecord);
		}

		// 封装消息
		{
			StairwayMessage.StairwayFighter.Builder fighterA = packFighter(teamA);

			StairwayMessage.StairwayFighter.Builder fighterB = packFighter(teamB);

			BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
			builder.setPlayback(battleHandle.playback(battleModule));// , team_a, team_b));

			response.setBattleResp(builder);// 录像

			response.setFighterA(fighterA);// 进攻方
			response.setFighterB(fighterB);// 防守方

			response.addAllRewards(new CurrencyHandle().packItems(rewards));
		}

		// 刷新对手
		LinkedList<Integer> list = randomMatch(rank);
		stairwayModuleA.getOppos().clear();
		stairwayModuleA.getOppos().addAll(list);
		stairwayModuleA.set();

		return Result.Success;
	}

	public Result costTimes(StairwayPlayerModule stairwayModule) {
		if (stairwayModule.remainTimes() <= 0 && stairwayModule.remainBuyTimes() <= 0) {
			return Result.StairwayTimesOut;// 没有次数了
		}
		if (stairwayModule.remainTimes() <= 0) {
			int costNum = fomula.天梯争雄购买次数元宝花费.intValue(stairwayModule.getBuytimes());
			Currency cost = Currency.create(CurrencyType.CT_元宝, 0, costNum);
			try {
				new CurrencyHandle().cost(stairwayModule.getPlayerCode(), CCReason.天梯争雄, cost);
			} catch (CurrencyNotEnoughException e) {
				return new Result(Result.CostFail, e.getType().getNumber(), e.getDataId());// 消费不足
			}
			stairwayModule.setBuytimes(stairwayModule.getBuytimes() + 1);
		} else {
			stairwayModule.setTimes(stairwayModule.getTimes() + 1);
		}
		return Result.Success;
	}

	public Result record(String playerCode, StairwayMessage.StairwayRecordResponse.Builder response) {
		List<StairwayRecord> list = StairwayRecord.get(playerCode);
		for (StairwayRecord record : list) {
			StairwayMessage.StairwayRecord.Builder builder = StairwayMessage.StairwayRecord.newBuilder();
			builder.setAttack(record.isAttacker());
			builder.setRecord(record.getRecordCode());
			builder.setDate(record.getDate().getMillis());

			StairwayMessage.StairwayFighter.Builder fighter = StairwayMessage.StairwayFighter.newBuilder();
			fighter.setNickname(record.getName());
			fighter.setHead(record.getHead());
			fighter.setLevel(record.getLevel());
			fighter.setPower(record.getPower());
			builder.setFighter(fighter);

			builder.setRank(record.getRank());
			builder.setResult(record.getBattleResult().getNumber());

			response.addRecords(builder);
		}

		return Result.Success;
	}

	private StairwayMessage.StairwayFighter.Builder packFighter(TeamModule team) {
		StairwayMessage.StairwayFighter.Builder builder = StairwayMessage.StairwayFighter.newBuilder();
		builder.setNickname(team.getName());
		builder.setHead(team.getHead());
		builder.setLevel(team.getLevel());
		builder.setPower(team.getPower());
		return builder;
	}

	private PlayerBean playerByRank(int areaGroupId, int rank) {
		Collection<RankEntry> entrys = new RankStairway(areaGroupId).range((long) rank, (long) rank);
		if (entrys.size() <= 0) {
			return null;
		}
		for (RankEntry entry : entrys) {
			String playerCode = entry.getKey();
			PlayerBean playerBean = PlayerBean.get(playerCode);
			if (playerBean != null) {
				return playerBean;
			}
		}
		return null;
	}

	private TeamModule team(int areaGroupId, int rank) {
		PlayerBean playerBean = playerByRank(areaGroupId, rank);
		if (playerBean != null) {
			// 真玩家
			//todo 修改登录时间，3天后自动清除缓存
			StatHandle.stat_用户登录状态更新(playerBean.getCode());

			return new BattleHandle().teamPlayer(playerBean.getCode(), FormatType.普通);
		}
		// NPC
		sportsrobot robotdata = DataCenter.getData(rank, sportsrobot.class);
		if (robotdata == null) {
			return null;
		}
		TeamModule team = new TeamModule();

		ArrayList<FighterModule> fighterModuleList = getFighterModuleList(rank);

		// 武将
		for (int i = 0; i < robotdata.getHeroid().length; i++) {
			Position position = Position.forValue(i + 1);
			int heroid = robotdata.getHeroid()[i];
			if (heroid == -1) continue;
			FighterModule fighterModule = fighterModuleList.get(i);
			team.addfighter(position, fighterModule);
		}
		// 神器
		WeaponModule weapon = WeaponModule.create(robotdata.getWeapondataid(), robotdata.getWeaponlv(), 0, 0, robotdata.getWeaponskilllv());
		team.setWeapon(weapon);

		long totalPower = 0;
		for (FighterModule fighterModule : fighterModuleList) {
			totalPower +=fighterModule.getTotalPower();
		}

		// 信息
		team.setName(robotdata.getName());
		team.setHead(robotdata.getHeadid());
		team.setLevel(robotdata.getPlayerlv());
		team.setPower(totalPower);

		return team;
	}

	public Result playerInfo(int areaGroupId, int rank, StairwayMessage.StairwayPlayerInfoResponse.Builder response) {
		PlayerBean playerBean = playerByRank(areaGroupId, rank);
		int vip = 0;
		if (playerBean == null) {
			sportsrobot robotdata = DataCenter.getData(rank, sportsrobot.class);
			if (robotdata == null) {
				return Result.ParamError;
			}
			vip = robotdata.getVip();
		} else {
			vip = playerBean.getViplevel();
		}

		TeamModule team = team(areaGroupId, rank);
		PlayerMessage.PlayerInfo.Builder builder = PlayerMessage.PlayerInfo.newBuilder();
		if (team == null) {
			return Result.ParamError;
		}
		builder.setNickname(team.getName());
		builder.setPower(team.getPower());
		builder.setLevel(team.getLevel());
		builder.setHead(team.getHead());
		builder.setVip(vip);
		for (FighterModule fighter : team.fighters().values()) {
			HeroMessage.HeroSimple.Builder heroSimple = HeroMessage.HeroSimple.newBuilder();
			heroSimple.setDataId(fighter.getHeroId());
			heroSimple.setLevel(fighter.getLevel());
			heroSimple.setStar(fighter.getStarlv());
			builder.addHeros(heroSimple);
		}
		response.setPlayerInfo(builder);
		response.setRank(rank);

		return Result.Success;
	}

	// 时间控制===========================================================================

	static public DateTime updateTime(DateTime time) {
		int week = time.getDayOfWeek();// 星期
		switch (week) {
		case 6:
			return time.withTimeAtStartOfDay().plusDays(1).plusHours(23);
		case 7:
			if (time.getHourOfDay() < 23) {
				return time.withTimeAtStartOfDay().plusHours(23);
			}

			return time.withTimeAtStartOfDay().withDayOfWeek(6).plusWeeks(1);
		default:
			return time.withTimeAtStartOfDay().withDayOfWeek(6);
		}
	}

	public static boolean isOpen(int areaGroupId) {
		StairwayModule module = StairwayModule.get(areaGroupId);
		return module.isOpening();
	}

	/** 开赛操作 */
	public void open(StairwayModule module, DateTime now) {
		// 初始化排行榜
		// 初始化天梯王者
		new RankStairway(module.getAreaGroupId()).clear();
		module.setCode(StairwayModule.code(now));
	}

	/** 结算操作 */
    public void settle(StairwayModule module) {
        // 结算邮件
        RankStairway rankStairway = new RankStairway(module.getAreaGroupId());
        ArrayList<RankEntry> top = new ArrayList<>();
        Map<String, sportsrankreward> all = DataCenter.getAllData(sportsrankreward.class);
        for (sportsrankreward data : all.values()) {
            Currencies rewards = new Currencies(Currency.create(data.getRewardtype(), data.getRewardid(), data.getRewardnum()));
            int rankStart = data.getRankingmin();
            int rankEnd = data.getRankingmax();
            Collection<RankEntry> entrys = rankStairway.range((long) rankEnd, (long) rankStart);

            for (RankEntry entry : entrys) {
                String playerCode = entry.getKey();
                long rank = entry.getValue();

                String title = GameString.天梯争雄排名奖励_title(rank).getText();
                String content = GameString.天梯争雄排名奖励_msg(rank).getText();
                new MailHandle().sendMail(playerCode, MailTypeEnum.Mail, title, content, CCReason.天梯争雄, rewards);
                if (rank <= 3) {
                    top.add(entry);
                }
            }
        }

        // 称号更换
        {
            RankStairwayKing rankStairwayKing = new RankStairwayKing(module.getAreaGroupId());
            Collection<RankEntry> kings = rankStairwayKing.all();
            for (RankEntry king : kings) {
                String kingCode = king.getKey();
                int kingRank = king.getValue().intValue();

                for (RankEntry entry : top) {
                    String playerCode = entry.getKey();
                    int rank = entry.getValue().intValue();
                    if (kingRank == rank) {
                        if (!kingCode.equals(playerCode)) {
                            try {
                                new CurrencyHandle().cost(kingCode, CCReason.天梯争雄, title(kingRank));
                            } catch (CurrencyNotEnoughException e) {
                            }
                        }
                        break;
                    }
                }
            }
            rankStairwayKing.clear();
            for (RankEntry entry : top) {
                rankStairwayKing.put(entry.getKey(), entry.getValue());
            }
        }
    }

	private Currency title(int rank) {
		switch (rank) {
		case 1:
			return Currency.create(CurrencyType.CT_称号, 201, 1);
		case 2:
			return Currency.create(CurrencyType.CT_称号, 202, 1);
		case 3:
			return Currency.create(CurrencyType.CT_称号, 203, 1);
		}
		return null;
	}


	//获取内存怪物战力属性
	public ArrayList<FighterModule> getFighterModuleList(int rank){
		RMap<String, ArrayList<FighterModule>> rMap = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client().getMap("INIT:sportsrobot");
		JSONArray arrary = (JSONArray) JSONArray.toJSON(rMap.get(String.valueOf(rank)));
		ArrayList<FighterModule> fighterModules = JSON.parseObject(arrary.toString(), new TypeReference<ArrayList<FighterModule>>() {
		});
		return fighterModules;
	}
}
